#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：python_learning 
@File ：抽象工厂模式.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/3/1 17:53 
"""

"""
抽象工厂模式 (Abstract Factory Pattern)
抽象工厂模式是一种创建型设计模式，提供一个创建一系列相关或相互依赖对象的接口，而无需指定它们具体的类。抽象工厂模式将一族产品的实例化延伸到具体工厂的子类。

在 Python 中，实现抽象工厂模式时通常使用抽象基类（ABC）和具体子类。以下是一个简单的示例：

在这个示例中，我们定义了两个抽象产品类 AbstractProductA 和 AbstractProductB，以及四个具体产品类。然后定义了抽象工厂类 AbstractFactory，其中包含了创建产品A和产品B的抽象方法。

具体工厂类 ConcreteFactory1 和 ConcreteFactory2 分别实现了抽象工厂类，每个工厂类都能够创建一组相关的产品。

在客户端代码中，我们可以选择使用具体的工厂类来创建一组相关的产品。这有助于确保产品之间的兼容性，并使得系统更容易进行扩展。
"""

from abc import ABC, abstractmethod


# 抽象产品A
class AbstractProductA(ABC):
	@abstractmethod
	def operation(self):
		pass


# 具体产品A1
class ConcreteProductA1(AbstractProductA):
	def operation(self):
		return "具体产品A1的操作"


# 具体产品A2
class ConcreteProductA2(AbstractProductA):
	def operation(self):
		return "具体产品A2的操作"


# 抽象产品B
class AbstractProductB(ABC):
	@abstractmethod
	def operation(self):
		pass


# 具体产品B1
class ConcreteProductB1(AbstractProductB):
	def operation(self):
		return "具体产品B1的操作"


# 具体产品B2
class ConcreteProductB2(AbstractProductB):
	def operation(self):
		return "具体产品B2的操作"


# 抽象工厂
class AbstractFactory(ABC):
	@abstractmethod
	def create_product_a(self) -> AbstractProductA:
		pass

	@abstractmethod
	def create_product_b(self) -> AbstractProductB:
		pass


# 具体工厂1
class ConcreteFactory1(AbstractFactory):
	def create_product_a(self) -> AbstractProductA:
		return ConcreteProductA1()

	def create_product_b(self) -> AbstractProductB:
		return ConcreteProductB1()


# 具体工厂2
class ConcreteFactory2(AbstractFactory):
	def create_product_a(self) -> AbstractProductA:
		return ConcreteProductA2()

	def create_product_b(self) -> AbstractProductB:
		return ConcreteProductB2()


# 客户端代码
def client_code(factory: AbstractFactory):
	product_a = factory.create_product_a()
	product_b = factory.create_product_b()

	result = f"{product_a.operation()} 和 {product_b.operation()}"
	print(result)


if __name__ == "__main__":
	# 使用具体工厂1
	client_code(ConcreteFactory1())
	# 输出：具体产品A1的操作 和 具体产品B1的操作

	# 使用具体工厂2
	client_code(ConcreteFactory2())
	# 输出：具体产品A2的操作 和 具体产品B2的操作
